﻿using System;
using System.Collections.Specialized;
using System.Windows.Input;
using LukasKopenec.LocalizationSupport;
using Microsoft.Win32;
using Notoric.Gui.Windows;

namespace Notoric.Gui.Commands
{
    /// <summary>
    /// Implements a command that saves the currently open project under a user given filename.
    /// </summary>
    /// <remarks>
    /// <para>
    /// The command can execute is and only if the Projects collection of the Project Explorer 
    /// window contains 1 <see cref="Notoric.ViewModel.Elements.Project"/> instance.
    /// </para>
    /// <para>
    /// The execution proceeds as follows:
    /// <list type="number">
    /// <item>
    /// The <see cref="SaveFileDialog"/> is showed, the filename is prefilled with the 
    /// <see cref="Notoric.ViewModel.Elements.Project.FileName"/> property or,
    /// if it is <see langword="null"/>, with the value returned by 
    /// the <see cref="Notoric.ViewModel.Elements.Project.SuggestFileName"/> method.
    /// </item>
    /// <item>
    /// If the user confirms the dialog, the command sets <see cref="Notoric.ViewModel.Elements.Project.FileName"/>
    /// to the value that user selected and calls <see cref="Notoric.ViewModel.Elements.Project.Save"/>.
    /// Otherwise, the exeuction stops.
    /// </item>
    /// </list>
    /// </para>
    /// </remarks>
    public class SaveAsCommand : RibbonCommand
    {
        #region Constructors

        /// <summary>
        /// Creates a new <see cref="SaveAsCommand"/> instance.
        /// </summary>
        /// <param name="mainWindow">
        /// <para>
        /// Type: <see cref="MainWindow"/>
        /// </para>
        /// <para>
        /// Reference to the application's main window.
        /// </para>
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// The <paramref name="mainWindow"/> is <see langword="null"/>.
        /// </exception>
        public SaveAsCommand(MainWindow mainWindow)
            : base(mainWindow)
        {
            mainWindow.ProjectExplorer.Projects.CollectionChanged += new NotifyCollectionChangedEventHandler(Projects_CollectionChanged);
            ScreenTipTitle = (string)LocalizationManager.GetValue("Ribbon.CommandTitles.AppMenu.Save");
        }

        #endregion

        #region ICommand Members

        /// <inheritdoc/>
        public override bool CanExecute(object parameter)
        {
            return ApplicationWindow.ProjectExplorer.Projects.Count == 1;
        }

        /// <inheritdoc/>
        public override void Execute(object parameter)
        {
            var project = ApplicationWindow.ProjectExplorer.Projects[0];
            
            SaveFileDialog dialog = new SaveFileDialog();

            dialog.AddExtension = true;
            dialog.Filter = "Notoric Project (*.ntp)|*.ntp";
            dialog.OverwritePrompt = true;
            dialog.Title = (string)LocalizationManager.GetValue("Application.SaveAsDialog.Title");
            dialog.FileName = project.FileName ?? project.SuggestFileName();

            bool? result = dialog.ShowDialog();

            if (result == true)
            {
                Mouse.OverrideCursor = Cursors.Wait;
                project.FileName = dialog.FileName;
                project.Save();
                ApplicationWindow.AddToRecentFilesList(project.FileName);
                Mouse.OverrideCursor = null;
            }
        }

        #endregion

        #region Event Handlers

        /// <summary>
        /// Occurs when the projects collection of the project explorer window has changed.
        /// </summary>
        /// <remarks>
        /// <b>Operation:</b><br/>
        /// The handler raises the <see cref="RibbonCommand.CanExecuteChanged"/> event.
        /// </remarks>
        /// <param name="sender">Object that has sent the event</param>
        /// <param name="e">Event data</param>
        private void Projects_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            RaiseCanExecuteChanged();
        }

        #endregion
    }
}
